package org.jeecg.modules.boc.utils.http;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 使用httpClient进行https模拟请求
 * 该类可独立运行
 *
 * @author pdz 2018-01-14 下午 11:32
 **/
@Slf4j
public class HttpsClient {

    private static ThreadSafeClientConnManager clientConnectionManager = null;
    private static DefaultHttpClient client = null;

    private static final String HTTP = "http";
    private static final String HTTPS = "https";
    private static final String SSL = "SSL";
    private static final String CHARSET = "UTF-8";
    private static final String CONTENT_TYPE = "application/x-www-form-urlencoded;charset=" + CHARSET;
    private static final int CONNECTION_OUT_TIME = 30000;//连接超时时间
    private static final int RESPONSE_OUT_TIME = 60000;//响应超时时间
    private static final int HTTP_PROT = 80;
    private static final int HTTPS_PROT = 443;
    private static final int ROUTE = 400;// 最大同时连接数
    private static final int TOTAL = 800;// 最大连接数

    static {
        try {

            log.info("static 方法");

            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme(HTTP, HTTP_PROT, PlainSocketFactory.getSocketFactory()));

            SSLContext sslContext = SSLContext.getInstance(SSL);
            sslContext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, null);

            SSLSocketFactory sslSf = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            schemeRegistry.register(new Scheme(HTTPS, HTTPS_PROT, sslSf));

            clientConnectionManager = new ThreadSafeClientConnManager(schemeRegistry);
            clientConnectionManager.setDefaultMaxPerRoute(ROUTE);
            clientConnectionManager.setMaxTotal(TOTAL);

            client = new DefaultHttpClient(clientConnectionManager);
            client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_OUT_TIME);
            client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, RESPONSE_OUT_TIME);

        } catch (Exception e) {
            log.info("http请求连接失败:"+e);
            throw new RuntimeException(" http请求连接失败!");
        }
    }

    private static class TrustAnyTrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    public static void main(String[] args) throws Exception {
        HttpsClient httpsClient = new HttpsClient();
//        httpsClient.httpsGet("https://www.baidu.com");
//        httpsClient.httpsGet("https://mztapp.fujian.gov.cn:20093/EidServer");

//        httpsClient.httpsPost("https://www.baidu.com","");
        httpsClient.httpsPost("https://mztapp.fujian.gov.cn:20093/EidServer/jaxrs/eid/SimAuthCallback", "{'1':'2'}");
    }

    /**
     * httpsGet方式
     *
     * @param url 请求rul
     */
    public JSONObject httpsGet(String url) throws Exception {

        log.info("httpsGet方式 请求 url：{}",url);

        // A:设置HttpClient
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);// 连接超时
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);// 响应超时

        // C:创建请求方法实例并指定请求地址
        HttpGet httpGet = new HttpGet(url);
        // D:设置请求头信息
//        httpGet.setHeader("Content-type", CONTENT_TYPE);
        httpGet.setHeader("Content-type", "application/json;charset=UTF-8");

        JSONObject resultJSON = new JSONObject();
        try {
            // E:发送请求
            HttpResponse res = client.execute(httpGet);

            // F:获取响应码
            int i = res.getStatusLine().getStatusCode();
            log.info("httpsGet响应码:{},res:{},res.getEntity()" , i ,res,res.getEntity());
            if (i == HttpStatus.SC_OK) {
                // G:获取返回数据
                HttpEntity entity = res.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                // 返回结果
                log.info("返回结果："+result);
                resultJSON = JSONObject.parseObject(result);
                log.info("返回结果-resultJSON："+resultJSON);
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.info("e:{}"+e);
        } finally {
            if (!httpGet.isAborted())
                httpGet.abort();
        }
        return resultJSON;
    }

    /**
     * httpsPost方式
     *
     * @param url   请求url
     * @param param 参数
     */
    public JSONObject httpsPost(String url, String param) throws Exception {
        log.info("httpsPost 请求方式----url:{},param:{}",url,param);

        // A:设置HttpClient
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);// 连接超时
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);// 响应超时

        // C:创建请求方法实例并指定请求地址
        HttpPost httpPost = new HttpPost(url);
        // D:设置请求头信息
//        httpPost.setHeader("Content-type", CONTENT_TYPE);
        httpPost.setHeader("Content-type", "application/json;charset=UTF-8");
//        httpPost.setHeader("Content-type", "application/json;charset=UTF-8");

        JSONObject resultJSON = new JSONObject();
        try {

            // 设置请求参数  方式：1
//            List<NameValuePair> formparams = new ArrayList<NameValuePair>();
//            formparams.add(new BasicNameValuePair("name", "admin"));
//            formparams.add(new BasicNameValuePair("phone", "123456"));
//            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");

            // E:设置请求参数 方式：2（param=“name=pdz&password=111111”）
            StringEntity stringEntity = new StringEntity(param.toString());
            stringEntity.setContentEncoding("UTF-8");
            httpPost.setEntity(stringEntity);

            // F:发送请求
            HttpResponse res = client.execute(httpPost);
            // G:获取响应码
            int i = res.getStatusLine().getStatusCode();
            log.info("httpsPost响应码:{},res:{},res.getEntity()" , i ,res,res.getEntity());
            if (i == HttpStatus.SC_OK) {
                // H:获取返回数据
                HttpEntity entity = res.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                // 返回结果
                log.info("返回结果："+result);
                resultJSON = JSONObject.parseObject(result);
                log.info("返回结果-resultJSON："+resultJSON);
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.info("e:{}"+e);
        } finally {
            if (!httpPost.isAborted())
                httpPost.abort();
        }
        return resultJSON;
    }

    /**
     * httpsPost发送json
     *
     * @param url   请求url
     * @param param 请求参数
     */
    public void httpsPostJson(String url, String param) throws Exception {

        // A:设置HttpClient
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);// 连接超时
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);// 响应超时

        // C:创建请求方法实例并指定请求地址
        HttpPost httpPost = new HttpPost(url);
        // D:设置请求头信息
        httpPost.setHeader("Content-type", "application/json;charset=UTF-8");// 这里是指定接收的数据类型

        try {
            // E:设置请求参数 （此处json）
            StringEntity stringEntity = new StringEntity(param.toString(), "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");//发送json数据需要设置contentType（这里是指定发送的数据类型）
            httpPost.setEntity(stringEntity);

            // F:发送请求
            HttpResponse res = client.execute(httpPost);

            // G:获取响应码
            int httpStatus = res.getStatusLine().getStatusCode();
            log.info("httpsPostJson响应码:" + httpStatus);
            if (httpStatus == HttpStatus.SC_OK) {
                // H:获取返回数据
                HttpEntity entity = res.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");// 返回json格式

                // 打印返回结果
                log.info(result);

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!httpPost.isAborted())
                httpPost.abort();
        }

    }

    /**
     * httpPost上传文件
     *
     * @param url  请求url
     * @param file 需上传文件
     */
    public void httpsPostFile(String url, File file) throws Exception {

        // A:设置HttpClient
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);// 连接超时
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);// 响应超时

        // C:创建请求方法实例并指定请求地址
        HttpPost httpPost = new HttpPost(url);
        // D:设置文件上传字符集
        MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Charset.forName("UTF-8"));

        try {

            // E:设置参数
            mpEntity.addPart("strKey", new StringBody("strValue", Charset.forName("UTF-8")));// 参数为字符串
            mpEntity.addPart("fileKey", new FileBody(file));// 参数为文件
            httpPost.setEntity(mpEntity);

            // F:发送请求
            HttpResponse response = client.execute(httpPost);

            // G:获取响应码
            int httpStatus = response.getStatusLine().getStatusCode();
            log.info("httpsPostJson响应码:" + httpStatus);
            if (httpStatus == HttpStatus.SC_OK) {

                // H:获取返回数据
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity);// 返回json格式

                // 打印返回结果
                log.info(result);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!httpPost.isAborted())
                httpPost.abort();
        }

    }

}
